package com.yz.rabbitmqspring;

import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
import org.springframework.amqp.rabbit.listener.api.ChannelAwareMessageListener;
import org.springframework.amqp.support.ConsumerTagStrategy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.UUID;

@Configuration
public class RabbitmqConfig {

    @Bean
    public ConnectionFactory connectionFactory(){
        CachingConnectionFactory factory = new CachingConnectionFactory();
        factory.setAddresses("azyjz.ltd:5672");
        factory.setUsername("zhang");
        factory.setPassword("zhang");
        factory.setVirtualHost("/");
        return factory;
    }

    /***
     *用于创建交换机、队列及绑定关系
     * */
    @Bean
    public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory){
        RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory);
        rabbitAdmin.setAutoStartup(true); //服务启动加载此对象
        return rabbitAdmin;
    }

    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory){
        return  new RabbitTemplate(connectionFactory());
    }

    /**
     * 声明式配置amqp
     *
     * 1.设置交换机类型
     * 2.将队列绑定到交换机
     *
     * FanoutExchange 将消息分发到与此交换机绑定的队列，不需要路由键
     * DirectExchange  按照routing key 转发消息到指定队列
     * TopicExchange  多关键字匹配
     * */

    @Bean
    public TopicExchange topicExchange(){
        return  new TopicExchange("amqp-topic-exchange",true,false);
    }

    @Bean
    public Queue topicQueue(){
        return  new Queue("amqp-topic-queue",true);
    }

    @Bean
    public Binding binding(){
        return BindingBuilder.bind(topicQueue()).to(topicExchange()).with("spring.#");
    }

    //声明queue交给spring 容器，容器启动后会创建此queue
    /**
     * 原理
     * {@link RabbitAdmin#afterPropertiesSet()}
     * {@link org.springframework.amqp.rabbit.core.RabbitAdmin#initialize()}
     * */
    @Bean
    public Queue imagesQueue(){
        Queue queue = new Queue("iamge-queue",true);
        return  queue;
    }

    @Bean
    public Queue pdfQueue(){
        return new Queue("pdf-queue",true);
    }
    /**
     * 消费者端，可监听多个队列
     * */
    @Bean
    public SimpleMessageListenerContainer simpleMessageListenerContainer(ConnectionFactory connectionFactory){
        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
        container.addQueues(topicQueue(),imagesQueue(),pdfQueue());
        container.setConcurrentConsumers(1);
        container.setMaxConcurrentConsumers(3);
        container.setPrefetchCount(1);
        container.setAcknowledgeMode(AcknowledgeMode.AUTO);
        //设置 ConsumerTag
        container.setConsumerTagStrategy(new ConsumerTagStrategy() {
            @Override
            public String createConsumerTag(String queue) {
                return queue+ UUID.randomUUID().toString();
            }
        });
        //设置消息监听器
        /**
         * 1.传入 {@link ChannelAwareMessageListener}接口
         * 1.1实现{@link ChannelAwareMessageListener#onMessage(org.springframework.amqp.core.Message, com.rabbitmq.client.Channel)}方法
         * */
        container.setMessageListener(new ChannelAwareMessageListener() {
            @Override
            public void onMessage(Message message, Channel channel) throws Exception {
                System.err.println("-----消费者------"+message);
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            }
        });

        /**
         * 2.1 创建{@link org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter} 传入自定义对象
         * 2.2 自定义对象默认 需要有#handleMessage方法，并且入参为byte[]
         * 2.3 可以修改#handleMessage名称且入参
         * */
//        MessageListenerAdapter listenerAdapter = new MessageListenerAdapter(new MessageDelegate());
//        container.setMessageListener(listenerAdapter);

        /**
         * 3.1 修改{@link MessageListenerAdapter} 默认调用方法名 #handleMessage
         * */
//        MessageListenerAdapter listenerAdapter = new MessageListenerAdapter(new MessageDelegate());
//        //修改默认调用的方法
//        listenerAdapter.setDefaultListenerMethod("myHandleMessage");
//        container.setMessageListener(listenerAdapter);
        /**
         * 4.1 修改{@link MessageListenerAdapter} 默认调用方法名 #handleMessage 且默认入参
         * */
        MessageListenerAdapter listenerAdapter = new MessageListenerAdapter(new MessageDelegate());
        //修改默认调用的方法
        listenerAdapter.setDefaultListenerMethod("myHandleMessage");
        //修改默认参数转换器，byte[] 转为string
        listenerAdapter.setMessageConverter(new TextMessageConverter());
        container.setMessageListener(listenerAdapter);

        return  container;
    }


}
